import evaluation_indicators as ev
from pyecharts.charts import Line
import pyecharts.options as opts
import csv
import dayCalculation as dc

#日志类，记录整个回测过程的详细情况
class Log:
    def __init__(self):
        self.log = {}

    #添加一天的记录
    def add_log(self, date, money, earning_rate, benchmark_money, benchmark_rate):  # 增加一条记录
        self.log[date] = {
            'money': money,
            'earning_rate': earning_rate,
            'benchmark_money': benchmark_money,
            'benchmark_rate': benchmark_rate
        }

    #统计一下各项指标
    def calculate(self):
        # 计算最大回撤
        money_list = [self.log[x]['money'] for x in self.log]
        rate_list = [self.log[x]['earning_rate'] for x in self.log]
        benchmark_list = [self.log[x]['benchmark_rate'] for x in self.log]
        #计算最大回撤、alpha、beta因子
        max_drawdown = ev.get_max_drawdown(money_list)
        alpha, beta = ev.get_alpha_beta(benchmark_list, rate_list)
        initial_date = list(self.log.keys())[0]
        last_date = list(self.log.keys())[-1]

        benchmark_info = {}
        #加载国债指数作为无风险利率
        with open('benchmark_data.csv', 'r') as f:
            reader = csv.reader(f)
            next(reader)
            for row in reader:
                benchmark_info[row[0]] = [float(row[1]), float(row[2])]
        no_risk_rate = benchmark_info[last_date][0] / benchmark_info[initial_date][0] - 1
        #计算夏普比率
        sharpe_ratio = ev.get_sharpe_ratio(rate_list, no_risk_rate)
        max_drawdown = format(max_drawdown,'.2%')
        alpha = format(alpha,'.2f')
        beta = format(beta,'.2f')
        sharpe_ratio = format(sharpe_ratio,'.2f')
        annual_return = (rate_list[-1]+1)**(1/(dc.date_diff(last_date, initial_date)/365))-1
        annual_return = format(annual_return,'.2%')

        return max_drawdown, alpha, beta, sharpe_ratio, format(rate_list[-1],'.2%'), annual_return
    
    # 给回测结果画个折线图，pyecharts YYDS
    def draw(self):  
        with open('log.txt', 'w') as f:
            for date in self.log:
                f.write(f'date:{date},info:{self.log[date]}\n')
        max_drawdown, alpha, beta, sharpe_ratio, overall_return, annual_return = self.calculate()
        
        line = (
            Line()
                .add_xaxis(list(self.log.keys()))
                .add_yaxis('实际收益', [format(self.log[x]['earning_rate'], '.2f') for x in self.log])
                .add_yaxis('基准收益：上证指数', [format(self.log[x]['benchmark_rate'], '.2f') for x in self.log])
                .set_global_opts(
                title_opts=opts.TitleOpts(title='回测结果'),
                yaxis_opts=opts.AxisOpts(min_='datamin'),
                graphic_opts=[
                    opts.GraphicGroup(
                        graphic_item=opts.GraphicItem(
                            left="70%",
                            top="2%",
                        ),
                        children=[
                            opts.GraphicText(
                                graphic_item=opts.GraphicItem(
                                    left="center",
                                    top="middle",
                                    z=100,
                                ),
                                graphic_textstyle_opts=opts.GraphicTextStyleOpts(
                                    text=
                                    f"overall_return:{overall_return}\n\n" + \
                                    f"annual_return:{annual_return}\n\n" + \
                                    f"max_drawdown:{max_drawdown}\n\n" + \
                                    f"alpha:{alpha}\n\n" + \
                                    f"beta:{beta}\n\n" + \
                                    f"sharpe_ratio:{sharpe_ratio}"
                                    ,
                                    font="14px Microsoft YaHei",
                                    graphic_basicstyle_opts=opts.GraphicBasicStyleOpts(
                                        fill="#333"
                                    )
                                )
                            )
                        ]
                    )
                ],
            )
        )
        line.render('line.html')
